﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef  Light_Manager_h
#define  Light_Manager_h

#include "include\\Utils\\Console.h"
#include "include\\Utils\\Timer.h"
#include "..\\import\\CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "..\\import\\param_trees_lib\\param_trees.h"
#include "include\\Objects\\light.h"

//#################################################################################################################
///// 
/////   :: КЛАСС МЕНЕДЖЕРА СВЕТА ::
///// 
//#################################################################################################################
class CLREngi_Light_Manager{
protected:
	typedef struct NODE_TYP{       // структура нашего растения %)
		unsigned int   id;                          // Идентификатор
		CLREngi_Light   *Light;
		NODE_TYP        *next;                       // Указатель на следующий узел списка
		NODE_TYP        *prev;                       // Указатель на предыдущий узел списка
	   }NODE,*NODE_PTR;
public:
unsigned int            LOADED_lights; // число камер
NODE_PTR                head;           // начало списка вамер
D3DXMATRIXA16          *matWorld;       // копия мировой 

CLREngi_Console        *Console;
//#################################################################################################################
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    bool           LoadFromRow(char *file){
		CRLEngi_string a;
		a = file;
		DynamicRow row;
		row.iLoadFromFile(a);
		//a = "[i] Loading lights from ";
		//a += file;
		//a += " ...";
		//Console->AddText(a,2); 
		LoadFromRow(&row);

		CRLEngi_string message;
		message = "[!] Light Manager setup completed with ";
		message += (int)LOADED_lights;
		message += " lights.";
		
		Console->AddText(message,3); 

		return true;	
	}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Чтение параметров из структуры
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	void          LoadFromRow(DynamicRow   *row){

		// подготовка к анализу структуры
		int id1 = 0, count,id2 = 0;
		CRLEngi_string LightName;
		LightName = "";
		id1 = (*row).iLookId("_LIGHTS_");
        count =  (*row).iCountKnots(id1) + (*row).iCountParams(id1);
		if (id1>0)
			if (count>0){
			   id2     = (*row).TopId(id1);
			   LightName = (*row).iLookName(id2);
               CreateNewLight(LightName,row);
			   for (int i=1;i<count;i++){
				   id2     = (*row).NextId(id2);
				   LightName = (*row).iLookName(id2);
                   CreateNewLight(LightName,row);
			     }//for
			   }//if
	}//void
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Создание света из параметров структуры
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned int  CreateNewLight(CRLEngi_string LightName,DynamicRow   *row){

		    // Вставка узла в конец списка
			NODE_PTR new_node = NULL;
			NODE_PTR curr;

			if (head == NULL) //Список пуст
				 curr = NULL; //(*head);
			else
			     curr = (head);

			// Создание нового узла
			// В C++ здесь используется оператор new
			new_node = (NODE_PTR)malloc(sizeof(NODE));
			//Заполняем поля
			LOADED_lights      += 1;
			(new_node->Light) = new CLREngi_Light();
			 new_node->Light->Light_setup(LightName,row);

			CRLEngi_string buffer;
			buffer = "[+] Light:  ";
			buffer += LightName.getChars();
			Console->AddText(buffer,0);
			
			//new_node->Parameters = row;
			new_node->id         = LOADED_lights;
			new_node->next       = NULL; // Лучше это делать всегда;
			// в данном случае наш узел будет
			// последним в списке, так что это
			// просто необходимо
			// Поиск конца списка и вставка
			if (curr == NULL){ //Список пуст
				(head) = new_node;
				return(new_node->id);
				}//if
			else{
				while(curr->next != NULL) curr  = curr->next;
				curr->next = new_node;
				new_node->prev = curr;
				return(new_node->id);
				}//else
		}//func
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	void              SetupEffect(ID3DXEffect *aEffect,unsigned int LiId){
	
		NODE_PTR curr;
        curr = head;
		while (true){
			if (curr->id==LiId){
				
				break;			
			}
			if(curr->next == NULL) break;
			curr = curr->next;
		 }

		/*if ((curr->id==1)||(curr->id==3))
		{curr->Light->Position.y+=0.1f;
		curr->Light->Color.x +=0.0001f;
		curr->Light->Color.y +=0.0002f;
		curr->Light->Color.z +=0.0001f;
		}*/
	
			aEffect->SetVector( "LightPos",            &(curr->Light->Position));
			aEffect->SetVector( "LightColor",          &(curr->Light->Color));
			
			aEffect->SetFloat(  "LightFalloff",         (curr->Light->Falloff) );
		    aEffect->SetFloat(  "LightSpecular",        (curr->Light->Specular) );
		    aEffect->SetFloat(  "LightSpecular_Itens",  (curr->Light->Specular_Itens) );
		    aEffect->SetFloat(  "LightAmbient",         (curr->Light->Ambient) );
		    aEffect->SetFloat(  "Attenuation",          (curr->Light->Attenuation) );
	
	}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 	void RenderAllLight(LPDIRECT3DDEVICE9 *Device,
		                LPDIRECT3DTEXTURE9     *Texture1, 
	                    LPDIRECT3DTEXTURE9     *Texture2 ){

		 NODE_PTR curr;
         curr = head;
		while (true){
            curr->Light->Get_PrimitiveDrawing(Device,Texture1,Texture2);
			if(curr->next == NULL) break;
			curr = curr->next;
		 }

	
	}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	void          SetupEffectByCurrient(ID3DXEffect *aEffect){
	
	}
//#################################################################################################################
public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                     КОНСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   CLREngi_Light_Manager(D3DXMATRIXA16* GMatrix,CLREngi_Console   *Cnsl){ 
		LOADED_lights = 0;
		head = NULL;
		matWorld = GMatrix;
		Console = Cnsl ;
	};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                       ДЕСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ~CLREngi_Light_Manager(){
	};
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif 
